"""
Spyder Editor

This is a temporary script file.
"""
from tkinter import *
import random #随机数

import time
import tkinter as tk
import webbrowser

import tkinter.messagebox
from tkinter import messagebox
from tkinter.messagebox import *

from PIL import ImageTk, Image

import _thread
import pygame
import pygame as py

import tkinter
from threading import Timer
     
import os
    

def initBoard(  board, pics  ):
    for i in range(1, len( board )-1 ):
        for j in range(1,len(board[i])-1,   2 ):
            #随机生成图片
            num=random.randint(   1,pics+1 )
            board[i][j]=board[i][j+1]=num
            
            
            
def shuffleBoard( board ):
    for i in range( 0, 10*len(board)*len(board[0])  ):
        x1=random.randint(  1,len(board)-2 )
        y1=random.randint(  1,len(board[0])-2)
        x2=random.randint(  1,len(board)-2 )
        y2=random.randint(  1,len(board[0])-2)
         
        temp=board[x1][y1]
        board[x1][y1]=board[x2][y2]
        board[x2][y2]=temp
        
def showBoard( board ):
    for i in range(  0,len(board)):
        for j in range(  0,len(board[i])):
            if( board[i][j]!=0):
                index=board[i][j]
                pi=imgs[  index ]
                imageid=cv.create_image(     (   i*40+20,  j*40+20)    ,     image=pi  )
                image_map[i][j]=imageid
    #cv.pack()            

 
def beginCall():
    def start_game():
        global cols,rows,pics,board,image_map
        rows=rows_var.get()
        cols=cols_var.get()
        pics=pics_var.get()
        board=  [  [0   for y in range( cols+2)  ]   for x in  range(  rows+2) ]
        image_map=[   [0   for y in range(cols+2 )   ]   for x in   range( rows+2)  ]
        print(  board )
        initBoard(  board,pics )
        print(  board )
        shuffleBoard( board )
        print( board )
        showBoard(  board )  #显示  棋盘 
        param_window.destroy()
        
         #添加暂停按钮
        btn = tk.Button(root, text="暂停",relief="raised",bg='pink',command=pause)
        btn.place(relx=0.0385, rely=0.045, relwidth=0.1, relheight=0.1)
        
        #添加提示按钮
        btn_tip = tk.Button(root, text="游戏攻略",relief="raised",bg='pink',command=tip)
        btn_tip.place(relx=0.0385, rely=0.445, relwidth=0.1, relheight=0.1)
        
        #添加重排按钮
        btn_resort = tk.Button(root, text="重排",relief="raised",bg='pink',command=resort)
        btn_resort.place(relx=0.0385, rely=0.245, relwidth=0.1, relheight=0.1)
        
         #添加道具按钮
        btn_resort = tk.Button(root, text="道具",relief="raised",bg='pink',command=prop_detail)
        btn_resort.place(relx=0.0385, rely=0.645, relwidth=0.1, relheight=0.1)
        
        #时间柱
        counter()
        
    #显示游戏参数选择窗口 
    param_window=Toplevel(  root  )
    param_window.title("连连看参数设置")
    param_window.geometry('500x400')
    #行数输入
    rows_var=IntVar()#表示这个rows_var是一个整形变量
    rows_var.set( 8 )
    Label(  param_window,text='请输入行数：').place(  x=10,y=10 )#提示框
    #Entry就是一个输入框
    Entry( param_window, textvariable=rows_var   ).place( x=100,y=10 )
    #列数输入
    cols_var=IntVar()
    cols_var.set( 10 )
    Label(  param_window,text='请输入列数：').place(  x=10,y=60)
    Entry(  param_window, textvariable=cols_var   ).place( x=100,y=60 )
    #图片数输入
    pics_var=IntVar()
    pics_var.set( 8 )
    Label(  param_window,text='请输入图片数：').place(  x=10,y=110 )
    Entry( param_window, textvariable=pics_var   ).place( x=100,y=110 )
    #加入一个按钮
    Button(   param_window,text='开始',command=start_game ).place( x=200,y=160  )
    #增加时间柱
   
        
        

class Point:
    def _init_(  self,x=0,y=0):
        self.x=x
        self.y=y



def callback( event ):
    global p1,p2,selected_first
    global firstSelectedRectId,secondSelectedRectId

    print('你点了canvas')
    print(   '点的位置:x:', event.x,   'y:',event.y)
    x=event.x//40
    y=event.y//40
    print('这个位置对应的board中的下标为:x:',  x,    'y:',y, ',对应的值为:',board[x][y] )
    if(board[x][y]==0):
        print('此处无图片')
        return
    #else:
        #print("有图片，图片值为：",board[x][y],"它对应的图片的绘制id为：",image_map[x][y])
    if( selected_first==False):     #这表明是第一次选定图片
            #记录这个点的坐标
        p1=Point()
        p1.x=x
        p1.y=y
            #给选定的图片绘制一个边框，以做提示
            #                       左上角点的x,y        右下角的点的x,y     线宽    颜色
        firstSelectedRectId=cv.create_rectangle(   x*40,y*40,   x*40+40,y*40+40  ,  width=2,outline='red')
        selected_first=True
    else:
        p2=Point()
        p2.x=x
        p2.y=y
        if(      p1.x==p2.x  and  p1.y==p2.y):
            return
        secondSelectedRectId= cv.create_rectangle(  x*40,y*40,x*40+40,y*40+40,width=2,outline='red')
        cv.pack()
            #判断是否可以联接两个点，   算法
        if(    board[p1.x][p1.y]==board[p2.x][p2.y]  and  isEraseOk(  board,p1,p2  )  ):
            drawLinkLine(p1, p2)  #可以连接的话，绘制线上去
                
            pygame.mixer.Sound.play(eraseSound)   #指定待播放音效
                
            t=Timer(0.3,delayrun)#定时函数
            t.start()
                #消除
                #Selected_first=False
            board[p1.x][p1.y]=board[p2.x][p2.y]=0
            selected_first=False
                
                #t=Timer(0.3,delayrun)#定时函数
                #t.start()
                
            flag=checkGameOver( board )
            if( flag==True):
                pygame.mixer.Sound.play(finishSound)
                    
                messagebox.showinfo( title='提示',message='恭喜您，游戏结束')
                #cv.delete( firstSelectedRectId  )
                #cv.delete(   secondSelectedRectId  )
                #cv.delete(  image_map[p1.x][p1.y]   )
                #cv.delete(  image_map[p2.x][p2.y]   )
                
                #if isGameOver( board ):
                    #messagebox.showinfo(title='提示',message='游戏结束')
        else:
                #不同不能消
            cv.delete(  firstSelectedRectId   )
            cv.delete(    secondSelectedRectId  )
            selected_first=False
            pygame.mixer.Sound.play(errorSound)  #错误音效
                
        #cv.pack()
        
def delayrun():
    cv.delete( firstSelectedRectId  )
    cv.delete( secondSelectedRectId )
    cv.delete( image_map[p1.x][p1.y]  )
    cv.delete( image_map[p2.x][p2.y]  )
    #再删除连接线
    undrawLine()
    
    #pygame.mixer.Sound.play(music1)
    #time.sleep(3)
    #pygame.mixer.Sound.stop(music1)
    
def checkGameOver(board):
    for i in range( 0,len(board)):
        for j in range(0,len(board[i])):
            if(   board[i][j]!=0):
                return False
    return True



#道具
def prop_detail():
    global counter,point,selected_first,formerpoint
    counter = 0
    for x in range(1, len( board )-1):
        for y in range(1,len(board[x])-1,   2 ):
            point = Point(x, y)
            if counter < 2:
                # 是否是第一次遇到这个点
                if selected_first:
                    selected_first = False
                    # 把这个点保存下来
                    p1=Point
                    formerpoint=Point
                    counter += 1
                else:
                    p2=Point
                    if(   p1.x==p2.x  and  p1.y==p2.y):
                         selected_first = True
                         continue
                    else:
                        # 判断是否可以链接
                        link_type = same_picture( formerpoint,point )
                        if link_type:
                            delayrun()
                            selected_first = True
                            counter += 1
                            break
                        
    def same_picture(p1, p2):
        """
        判断两个点时候相同
        :param p1:
        :param p2:
        :return:
        """
        if board[p1.x][p1.y]==board[p2.x][p2.y]:
            return True
        else:
            return False
        



        

#帮助文档
def tip():
    #C:/Program Files/Internet Explorer/iexplore.exe为浏览器所在路径
    os.system('"C:/Program Files/Internet Explorer/iexplore.exe" https://max.book118.com/html/2020/1018/8050126016003007.shtm')
    
    
#暂停
def pause():
    try:
            pause = askyesno("提示", "点击继续")
            while True:
                time.sleep(1)
                if pause:
                    break
                else:
                    gamequit()
                    break

    except Exception as e:
            _ = e.__traceback__
            
#重排
def resort():
    #清空棋盘原有的值
    global cols,rows,pics,board,image_map
    rows=8
    cols=10
    pics=8
    board=  [  [0   for y in range( cols+2)  ]   for x in  range(  rows+2) ]
    image_map=[   [0   for y in range(cols+2 )   ]   for x in   range( rows+2)  ]
    
    cv.delete("all")
    #再次初始化打乱存值
    initBoard(  board,pics )
    shuffleBoard( board )
    showBoard(  board )  #显示  棋盘
    
    
def counter():
        """
        计时柱的构建
        :return:
        """
        global large_time,cycle,__time,add_time,scalar,game_start,n
        game_start=True 
        
        #时间柱
        time_counter = tk.Canvas( width=22, height=180, bg="pink")
        time_counter.place(x=620, y=80)
        print("cess")
        # 时间显示 
        show_time = tk.Label(root, bg="pink", fg="white", text=f"剩余时间\n{__time}s")
        show_time.place(x=610, y=20) 

        
        #时间流动
        fill_line=time_counter.create_rectangle(1.5, 1.5,23,0,width=0,fill="white")
        while cycle>0:
            if game_start:
                n+=scalar
                time_counter.coords(fill_line,(0,0,80,n))
                root.update()
                show_time.configure(text=f"剩余时间\n{__time}s", fg="white")
                __time-=1
                time.sleep(1.0)
                if __time==0:
                    tk.messagebox.showinfo("Tip,f","最后分数：{__score}")
                    game_start=False
                    cycle=__time
            else:
                break
                
            

def isEraseOk( board,p1,p2):
    if (doOneLine( board,p1,p2) or doTwoLine( board,p1,p2) or doThreeLine( board,p1,p2)):
        return True
    else:
        return False

def doOneLine( board,p1,p2 ):
    minValue=0
    maxValue=0
    if p1.x==p2.x:
        minValue=min(   p1.y,p2.y  )
        maxValue=max(   p1.y,p2.y  )
        
        for i in range( minValue+1,maxValue):
            if (board[p1.x][i]!=0):
                return False
        return True
    elif p1.y==p2.y:
        
        minValue=min( p1.x,p2.x)
        maxValue=max( p1.x,p2.x)
        
        for i in range(   minValue+1,maxValue):
            if (board[i][p2.y]!=0):
                return False
        return True
    else:
        
        return False

def doTwoLine( board,p1,p2 ):
    #构造两个点   t1(   p1.x,p2.y)     t2(  p2.x,p1.y )
    t1=Point()
    t1.x=p1.x
    t1.y=p2.y
    
    t2=Point()
    t2.x=p2.x
    t2.y=p1.y
    #判断t1本身是0，且，doOneLine(  t1,p1  )    doOneline(t1,p2)
    if(   board[t1.x][t1.y]==0  and  doOneLine(   board,t1,p1) and doOneLine( board,t1,p2) ):
        linePointStack.append( t1 )
        return True 
    #判断t2本身是0，且，doOneLine(  t2,p1  )   doOneLine( t2,p2)
    elif(   board[t2.x][t2.y]==0 and doOneLine( board,t2,p1) and doOneLine( board,t2,p2)):
        linePointStack.append( t2 )
        return True
    else:#否则表示两线不能消，返回False
        return False

def doThreeLine( board,p1,p2):
    #以p1点为核心，循环它的 x,构造一个新点，这个点与p1能一线连，且与p2能两线连，且自己还是0满足，则返回True
    for i in range( 0,len(board)):
        t=Point()
        t.x=i
        t.y=p2.y
        if(   board[t.x][t.y]==0 and doOneLine( board,t,p2) and doTwoLine( board,t,p1) ):
            linePointStack.append( t )
            return True
    #循环它的y,构造一个新点，这个点与p1能一线连，且与p2能两线连，且自己还是0满足，则返回True
    for j in range( 0,len( board[p2.x]  )):
        t=Point()
        t.x=p2.x
        t.y=j
        if(  board[t.x][t.y]==0 and doOneLine( board,t,p2) and doTwoLine( board,t,p1) ):
            linePointStack.append( t )
            return True
    return False

#画连线
def drawLinkLine(  p1,p2):
    if(   len( linePointStack  )  ==0):
        lineid=drawLine( p1,p2)
        line_id.append(   lineid )
    elif(  len( linePointStack)==1 ):
        z=linePointStack.pop()
        line1=drawLine( p1,z )
        line_id.append(   line1 )
        line2=drawLine(  z, p2 )
        line_id.append(   line2 )
        print('这是两线连')
    if( len( linePointStack) ==2 ):
        z=linePointStack.pop()
        
        line1=drawLine( p2,z )
        line_id.append(   line1 )
        
        z2=linePointStack.pop()
        line2=drawLine( z,z2)
        line_id.append(    line2 )
        
        line3=drawLine( p1,z2 )
        line_id.append(   line3 )
        
def undrawLine( ):
    global linePointStack
    while(   len( line_id)>0 ):
        lineid=line_id.pop()
        cv.delete(   lineid )
    line_id.clear()
    linePointStack.clear()
    
def drawLine( p1,p2):
    lineid=cv.create_line(  p1.x*40+20,p1.y*40+20,p2.x*40+20,p2.y*40+20 , width=2,fill='red')
    return lineid



m=180
n=0
game_start=False  #游戏状态
large_time=180    #上限时间
__time=large_time  #实现游戏时间，开始等于最大时间
add_time=5   #每次消除增加的时间和时间柱开始的时间
cycle=large_time  #循环量
scalar=180/cycle #矩形时间柱填充速率

selected_first=False

    
rows=0
cols=0
pics=0
board=[]   #棋盘对应的数组，里面全是数字  (0代表空图片，其他的数字代表对应的图片号)
image_map=[] 

#Selected_first=False

#打开指定图片5
#def get_image( filename,width,height):
    #im=Image.open( filename  ).resize(  (width,height))
    #return ImageTk.PhotoImage( im )

#游戏退出
def gamequit():
    pygame.mixer.music.stop()
    root.destroy()     #关闭窗口
    


root=Tk()
root.title("连连看")
root.geometry('700x500')

linePointStack=[]
line_id=[]

root.protocol("WM_DELETE_WINDOW",gamequit)


imgs=[   PhotoImage(  file='gif\\bar_'+str(i)+'.gif'    )      for i in range(0,12)    ]


#给root加一个菜单条
menubar=Menu(  root  )

#文件下拉菜单
menu_start=Menu(  menubar,    tearoff=False  )
menubar.add_cascade(menu=menu_start,label='开始')


menu_start.add_command(   label='开始游戏',     command=beginCall  )#点开始游戏时， 调用startGame函数
menu_start.add_command(   label='退出界面',     command=gamequit)

#显示到窗口
root.config(  menu=menubar )


eraseSoundfile=r'xiaoxin.mp3'      #消除音乐
errorSoundfile=r'失败音效.mp3'        #错误音乐
finishSoundfile=r'victory.mp3'      #胜利音乐
bgSoundfile=r'连连看背景音.mp3'    #背景音乐

pygame.mixer.init()
bgSound = pygame.mixer.music.load(bgSoundfile)
#bgSound = pygame.mixer.Sound(bgSoundfile)

eraseSound = pygame.mixer.Sound(eraseSoundfile)
errorSound = pygame.mixer.Sound(errorSoundfile)
finishSound = pygame.mixer.Sound(finishSoundfile)

#music1 = pygame.mixer.Sound(eraseSoundfile)
pygame.mixer.music.play(   loops=-1)       #无限循环
#pygame.mixer.music.stop()
#给root加一个菜单条
#menubar=Menu(  root  )



#显示到窗口
#root.config(  menu=menubar )

#加块画布
cv=Canvas(    root,bg='pink',width=400,height=500)
cv.bind("<Button-1>",callback)     #callback是回调函数


cv.pack()



root.mainloop()
